package com.xyzwps.orm.jooq.repository;

import com.xyzwps.orm.exception.TagDuplicateException;
import com.xyzwps.orm.model.Tag;
import com.xyzwps.orm.repository.TagRepository;
import com.xyzwps.orm.util.ExceptionUtils;
import org.jooq.DSLContext;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static org.jooq.impl.DSL.*;

public class JooqTagRepository implements TagRepository {

    private final DSLContext context;

    public JooqTagRepository(DSLContext ctx) {
        this.context = Objects.requireNonNull(ctx);
    }

    @Override
    public int insert(Tag tag) {
        try {
            // TODO: 并发时有木有问题
            context.insertInto(table("tag"), field("tag_name"), field("user_id"))
                    .values(tag.getTagName(), tag.getUserId())
                    .execute();
            return context.lastID().intValue();
        } catch (Exception ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.getTagName());
            }
            throw ex;
        }
    }

    @Override
    public void update(Tag tag) {
        try {
            context.update(table("tag"))
                    .set(field("tag_name"), tag.getTagName())
                    .set(field("user_id"), tag.getUserId())
                    .where(field("tag_id").eq(tag.getTagId()))
                    .execute();
        } catch (Exception ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.getTagName());
            }
            throw ex;
        }
    }

    @Override
    public void delete(int tagId) {
        context.deleteFrom(table("tag")).where(field("tag_id").eq(tagId)).execute();
    }

    @Override
    public Optional<Tag> selectByTagId(int tagId) {
        var tag = context.select(field("tag_id"), field("tag_name"), field("user_id"))
                .from(table("tag"))
                .where(field("tag_id").eq(tagId))
                .fetchOneInto(Tag.class);
        return Optional.ofNullable(tag);
    }

    @Override
    public List<Tag> selectAllForUser(int userId) {
        return context.select(field("tag_id"), field("tag_name"), field("user_id"))
                .from(table("tag"))
                .where(field("user_id").eq(userId))
                .fetchInto(Tag.class);
    }

}
